"""
面向对象：一切接对象，将现实世界需要进行抽象
类：与现实世界一对一映射 灯 Light（状态，颜色，开灯，关灯，调色）
    是抽象的，是一个模板（模具），决定了像什么
实例：是具体的，有具体数据，是什么 l1-l6 个具体的实例

封装：将数据以及数据的操作封装成类
继承：通过父子类关联（子类使用父类已经实现拥有的内容）避免重复代码的编写  __init__  __str__
多态：同一个类内容函数同名不同参数（*args）  父子类通过子类重写父类的功能实现

魔法函数： __**__  不需要自己调用
构造函数：用于创建实例（申请内存，存储实例），返回实例 object:  super().__new__()
初始化函数: 接受构造好的实例，并且向实例中添加属性数据 self.* = *
析构函数: 用于释放相关资源（释放内存）
转字符串函数： 将实例使用字符表示

实例属性：属于实例  类内self.*  类外实例.*
实例方法：数据实例  第一个形参self  类内self.*()  类外实例.*()
    import types   实例.实例方法名=types.TypeMethod(原方法，实例)
类属性: 属于类 定义在类中 类内类外类名.类属性=值  类名.类属性
类方法：属于类 第一个形参是cls 需要使用装饰器@classmethod
静态方法： 属于类 需要使用装饰器@staticmethod
注意： 实例 可以获取 类属性，类方法，静态方法

普通成员：public 公开的，所有位置都可以访问
保护成员：protect 类内以及子类可以访问
私有成员：private 只有类内可以访问 类外可以强制访问（不推荐）

封装属性：
1. 通过实例可以直接修改实例数据 p1.age = -50  (数据不合法)
2. 通过封装实例方法 确定实例能否修改成功
def  set_age(self,age):
    if  0<=age<=100：
        self.age = age
    else：
        pass
使用魔法  p1.set_age(-50)
3. 属性封装
    属性名=property(fset, fget)   获取属性触发 fget  设置属性触发 fset

    @property
    def name(self):
        return self.name

    @name.setter
    def name(self, name):
        self.name = name

多继承: 类拥有多个父类，拥有每一个父类的功能实现  类名.mro()  python    广度优先
单例类：只有唯一的实例  第一次使用 类名()创建实例 返回实例   后续直接返回原有的实例

class Manage:
    instance = None
    def __new__(cls):
        if Manage.instance is None:
            Manage.instance = super().__new__(cls)
        return Manage.instance

任何类继承Manage都成为单例类

__hasattr__
__getattr__
__setattr__
__delattr__

抽象类：不可以直接实例化  通过实例化抽象类的子类
抽象类（继承ABC， 编写抽象方法  @abstractmethod）

"""
# from abc import ABC, abstractmethod
#
# class Animal(ABC):
#     """
#     抽象类
#     """
#     @abstractmethod
#     def walk(self):
#         """
#         抽象函数
#         """
#         pass
#
# # a1 = Animal()
#
# class Cat(Animal):
#     def walk(self):
#         print("优哉游哉")
#
# c1 = Cat()


# class Manage:
#     def __new__(cls, *args, **kwargs):
#         if not hasattr(Manage, "instance"):
#             setattr(Manage, "instance",  super().__new__(cls))
#         return getattr(Manage, "instance")

# class Person:
#     passs
#
# p1 = Person()
# p2 = Person()

# print(hasattr(p1, "name"))
# # p1.name = "醒醒啦"
# setattr(p1, "name", "醒醒啦")
# print(hasattr(p1, "name"))
# print(p1.name)
# print(getattr(p1, "name"))
# # del p1.name
# delattr(p1, "name")
# print(hasattr(p1, "name"))


# 1. 空窗体 初始化 标题 logo
# 2. 初始化 菜单 画布 状态栏
# 3. 添加菜单事件  绘制矩形 直线 圆形  撤销 清除 退出
# 4. 添加鼠标事件 左键点击 左键拖拽 左键抬起 右键抬起
# 5. 当前选择图形 当前选择颜色  状态栏
# 6. 鼠标点下绘制图形  鼠标拖拽更新绘制  鼠标抬起结束绘制


import tkinter
from tkinter import colorchooser
from tkinter import messagebox


# class Draw:
#     def __init__(self):
#         self.root = tkinter.Tk()
#         self.root.title("画图")
#         self.root.iconbitmap("./favicon.ico")
#
#     def run(self):
#         self.root.mainloop()
#
# draw = Draw()
# draw.run()


class Draw:
    def __init__(self):
        self.root = tkinter.Tk()
        self.root.title("画图")
        self.root.iconbitmap("./favicon.ico")
        self.init_menu()
        self.init_canvas()
        self.init_event()
        self.init_status()

        self.max_id = None

        self.start_x = None
        self.start_y = None

        self.current_shape = "none"

        self.current_color = "black"

    def set_shape(self, shape):
        self.current_shape = shape

        if self.current_shape == "line":
            self.status.config(text=f"正在绘制直线")
        elif self.current_shape == "rect":
            self.status.config(text=f"正在绘制矩形")

        elif self.current_shape == "oval":
            self.status.config(text=f"正在绘制椭圆")

        elif self.current_shape == "none":
            self.status.config(text=f"选择图像后开始绘制")

    def set_color(self, color):
        self.current_color = color

    def choose_color(self):
        r = colorchooser.askcolor()
        if r[1]:
            self.set_color(r[1])

    def clear(self):
        self.canvas.delete("all")
        self.max_id = 0

    def undo(self):
        if self.max_id > 0:
            self.canvas.delete(self.max_id)
            self.max_id -= 1
    def init_menu(self):
        self.main_menu = tkinter.Menu(self.root)

        self.shape_menu = tkinter.Menu(self.root, tearoff=False)
        self.shape_menu.add_command(label="矩形", command=lambda: self.set_shape("rect"))
        self.shape_menu.add_command(label="圆形", command=lambda: self.set_shape("oval"))
        self.shape_menu.add_command(label="直线", command=lambda: self.set_shape("line"))

        self.main_menu.add_cascade(menu=self.shape_menu, label="图形")

        self.color_menu = tkinter.Menu(self.root, tearoff=False)
        self.main_menu.add_cascade(menu=self.color_menu, label="颜色")
        self.color_menu.add_command(label="红色", command=lambda: self.set_color("red"))
        self.color_menu.add_command(label="绿色", command=lambda: self.set_color("green"))
        self.color_menu.add_command(label="蓝色", command=lambda: self.set_color("blue"))
        self.color_menu.add_separator()
        self.color_menu.add_command(label="自定义", command=self.choose_color)

        self.other_menu = tkinter.Menu(self.root, tearoff=False)
        self.other_menu.add_command(label="清除", command=self.clear)
        self.other_menu.add_command(label="撤销", command=self.undo)
        self.other_menu.add_command(label="退出", command=self.root.destroy)
        self.main_menu.add_cascade(menu=self.other_menu, label="其他")

        self.root.config(menu=self.main_menu)

    def init_canvas(self):
        self.canvas = tkinter.Canvas(self.root, width=800, height=600)
        self.canvas.pack()

    def init_status(self):
        self.status = tkinter.Label(self.root, text="选择图像后开始绘制")
        self.status.pack(side="left")



    def begin_draw(self, e):
        if self.current_shape != "none":
            self.start_x = e.x
            self.start_y = e.y

            if self.current_shape == "line":
                self.max_id = self.canvas.create_line(self.start_x, self.start_y, self.start_x, self.start_y, fill=self.current_color)
            elif self.current_shape == "oval":
                self.max_id = self.canvas.create_oval(self.start_x, self.start_y, self.start_x, self.start_y, outline=self.current_color)
            elif self.current_shape == "rect":
                self.max_id = self.canvas.create_rectangle(self.start_x, self.start_y, self.start_x, self.start_y, outline=self.current_color)

    def update_draw(self, e):
        if self.current_shape != "none" and self.start_x is not None and self.start_y is not None:
            self.canvas.coords(self.max_id, self.start_x, self.start_y, e.x, e.y)

    def stop_draw(self, e):
        if self.current_shape != "none":
            self.start_x = None
            self.start_y = None

    def init_event(self):
        self.canvas.bind("<Motion>", self.update_draw)
        self.canvas.bind("<Button-1>", self.begin_draw)
        self.canvas.bind("<ButtonRelease-1>", self.stop_draw)
        self.canvas.bind("<ButtonRelease-3>", lambda e: self.set_shape("none"))

    def run(self):
        self.root.mainloop()


draw = Draw()
draw.run()
